import { createApp } from 'vue';
import App from './App.vue';
import * as utils from './libs/utils';
import MyUI from './libs/MyUI';

// 每个组件都是一个对象
// console.log(App);

// createApp(App).mount('#app');

// 也可以写成
const app = createApp(App);
// console.log(app);

// createApp 返回一个提供应用上下文的应用实例。
// 应用实例挂载的整个组件树共享同一个上下文
// const app = createApp({
//   name: 'App',
  // root component options
// })

// 现在所有的全局方法都已经挂载到这个实例上 而不再使用 Vue.xxxx
// 如全局挂载组件

// app.component('component-name', component);

// mount 将实例挂载到容器元素中
// 参数可以是实际的DOM元素，也可以是CSS选择器（将使用第一个匹配的元素）。返回根组件实例。
// 每个应用程序实例，mount() 只能调用一次。

// app.mount(document.body.firstChild)
// app.mount('#app');

// unmount 卸载已装载的应用程序实例(根组件)，触发应用程序组件树中所有组件的卸载生命周期挂钩。

// setTimeout(() => {
//   app.unmount('#app');
// }, 5000);

// 每个 Vue 应用都会暴露一个 config 对象，该对象包含此应用的配置设置
// console.log(app.config);

// 在挂载应用之前，可以修改其 property

// errorHandler 默认值 undefined
// 指定一个处理函数，来处理组方法件渲染和侦听器执行期间抛出的未捕获错误。
// 这个处理函数被调用时，可获取错误信息和应用实例。
app.config.errorHandler = (err, vm, info) => {
  // 处理错误
  // `info` 是 Vue 特定的错误信息，比如错误所在的生命周期钩子
  
}

// warnHandler 默认值 undefined
// 为 Vue 的运行时警告指定一个自定义处理函数。注意这只会在开发环境下生效，在生产环境下会被忽略
app.config.warnHandler = (msg, vm, trace) => {
  // `trace` 是组件的继承关系追踪

}

// globalProperties 默认值 undefined
// 添加一个可以在应用的任何组件实例中访问的全局 property。组件的 property 在命名冲突具有优先权。(组件内部的命名优先级更高)
// 这可以代替 Vue 2.x Vue.prototype 扩展

// Vue2做法
// new Vue({

// });
// Vue.prototype.utils = utils;
// Vue.prototype.$http = () => {};

// Vue3做法
app.config.globalProperties.utils = utils;
// app.config.globalProperties.$http = () => {};


// optionMergeStrategies 为自定义选项定义合并策略。(用的少)
// 合并策略选项分别接收在父实例和子实例上定义的选项的值作为第一个和第二个参数
// 自定义选项在合并时，默认策略为简单地覆盖已有值。

// 如果想让某个自定义选项以自定义逻辑进行合并，可以添加一个函数
app.config.optionMergeStrategies.custom = (toVal, fromVal) => {
  // console.log(fromVal, toVal);
  // 父组件内的 toVal => This is App\'s options
  // 子组件内的 fromVal => undefined
  // return mergedVal
  return fromVal || toVal;
}

// app.mixin({
//   utils
// })

// app.mixin({
//   custom: 'This is Mixin\'s option',
//   created() {
//     console.log(this.$options.custom);
//   }
// })


// performance 默认：false
// 设置为 true 以在浏览器开发工具的 performance/timeline 面板中启用对组件初始化、编译、渲染和更新的性能追踪。
// 只适用于开发模式和支持 performance.mark API 的浏览器

app.config.performance = true;


// config.compilerOptions 配置运行时编译器的选项。
// 设置在这个对象上的值将会被传入浏览器内的模板编译器，并影响配置过的应用内的每个组件。
// 注意，也可以使用 compilerOptions 选项在每个组件的基础上覆写这些选项

// 该配置选项只在完整的构建中生效 (例如可以在浏览器中编译模板的独立版 vue.js)。
// 如果使用的是附带额外构建设置的仅运行时版，编译器选项必须传入 @vue/compiler-dom 构建工具的配置来替代

// 对 vue-loader 来说：通过 compilerOptions loader 选项传入。也可以查阅 vue-cli 中的配置方式。(webpack)
// 对 vite 来说：通过 @vitejs/plugin-vue 选项传入。


// compilerOptions.isCustomElement
// 指定一个方法来识别 Vue 以外 (例如通过 Web Components API) 定义的自定义元素。
// 如果组件匹配了这个条件，就不需要本地或全局注册，Vue 也不会抛出 Unknown custom element 的警告
// 注意所有的原生 HTML 和 SVG 标记不需要被这个函数匹配——Vue 的解析器会自动检测它们。

// 任何 'charlie-' 开头的元素都会被识别为自定义元素
// Vue2 中
// Vue.config.ignoredElements = [
//   /^charlie-/,
  // ...
// ]
// Vue3 中
// app.config.compilerOptions.isCustomElement = tag => tag.startsWith('charlie-');


// compilerOptions.whitespace 默认值：'condense', 可选 'preserve'
// 默认情况下，Vue 会移除/压缩模板元素之间的空格以产生更高效的编译结果：
// 1.元素内的多个开头/结尾空格会被压缩成一个空格
// 2.元素之间的包括折行在内的多个空格会被移除
// 3.文本结点之间可被压缩的空格都会被压缩成为一个空格

// 设置 'preserve' 的值可以禁用 (2) 和 (3)


// compilerOptions.comments 默认值：false
// 默认情况下，Vue 会在生产环境下移除模板内的 HTML 注释。
// 将这个选项设置为 true 可以强制 Vue 在生产环境下保留注释。而在开发环境下注释是始终被保留的。
// 这个选项一般会用于依赖 HTML 注释的其它库和 Vue 配合使用

// app.config.compilerOptions.comments = true;


// use 使用插件 plugin
app.use(MyUI, {
  components: [ // 这个第二个参数可以在plugin 的options里获取
    'MyButton' 
  ]
});

app.mount('#app');